/*
 * EnvioDAO.java
 *
 * Created on 23 de octubre de 2007, 04:06 PM
 *
 * To change this template, choose Tools | Options and locate the template under
 * the Source Creation and Management node. Right-click the template and choose
 * Open. You can then make changes to the template in the Source Editor.
 */

package com.src.computec.radar.services.utilities.dao;

import com.src.computec.radar.base.dao.GenericDAO;
import com.src.computec.radar.base.dao.exception.DAOException;
import com.src.computec.radar.services.base.constantes.ConstantesGenerales;
import com.src.computec.radar.services.source.CoreServicesSource;
import com.src.computec.radar.services.utilities.dto.EnvioDto;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;

/**
 *
 * @author aocampo
 */
public class EnvioDAO extends GenericDAO implements BaseEnvioDAO {
    
    /** Creates a new instance of EnvioDAO */
    public EnvioDAO() {
    }
    
    /**
    * Retorna el envio EnvioDto correspondiente al codigo de barras ingresado como parametro
    *
    * @param codigoBarras String codigo de barras del envio buscado.
    * @return EnvioDto envio correspondiente al codigo de barras.
    */
    public EnvioDto getEnvioByCodigoBarras(String codigoBarras, Connection con) throws DAOException{
        EnvioDto envioDTO = null;
        PreparedStatement statement = null;
        ResultSet rs = null;
        try {
            statement = con.prepareStatement("SELECT CODIGO_BARRAS, CODIGO_ULTIMA_GESTION, NUMERO_ORDEN " +
                                             "FROM " + ConstantesGenerales.getInstance().SCHEMA + ".ENVIO " +
                                             "WHERE CODIGO_BARRAS = ?");
            statement.setString(1, codigoBarras);
            rs = statement.executeQuery();
            while (rs.next()) {
                int indice = 0;
                envioDTO = new EnvioDto();
                envioDTO.setCodigoBarras(rs.getString(++indice));
                envioDTO.setCodigoUltimaGestion(rs.getString(++indice));
		envioDTO.setNumeroOrden(rs.getString(++indice));
            }
        } 
        catch (SQLException e) {
            throw new DAOException("EnvioDAO:getEnvioByCodigoBarras: " + e.toString(), e);
        }
        finally {
            closeConnection(null, statement, rs);
        }
        return envioDTO;
    }
    
    /**
    * Actualiza el campo CODIGO_ULTIMA_GESTION de la tabla ENVIO con el valor
    * recibido en el parametro codigoGestion, para los envios en la lista envios
    * recibida como parametro.
    *
    * @param envios lista List con el codigo de barras de los envios a actualizar
    * @param codigoGestion String con el nuevo codigo de gestion
    * @param responsable nombre de usuario en LDAP de la persona que realiza la actualizacion
    * @return Hashtable con los envios que no se pudieron actualizar, este Hashtable tiene
    *         como key el codigo de barras y como valor el codigo de error segun los codigos
    *         de error del bundle DespachosSetup.properties.
    */
    public Hashtable updateGestionEnvios(List envios,String codigoGestion,String responsable) throws DAOException{
        Hashtable errores = new Hashtable();
        Iterator iteratorEnvios = envios.iterator();
        Connection con = null;
	ArrayList listOrdenes_=new ArrayList();
        try {
            con = getConnectionDB2();
            while (iteratorEnvios.hasNext()) {
                String codigoActual = (String) iteratorEnvios.next();
                EnvioDto envioAux = this.getEnvioByCodigoBarras(codigoActual, con);
                if (envioAux == null) {
                    errores.put(codigoActual, CoreServicesSource.getInstance().getCoreServicesSetupKey("inconsistenciaEnvioInexistente"));
                }
                else {
                    if (validarCambioGestion(codigoGestion, envioAux.getCodigoUltimaGestion())) {
                        this.updateGestionEnvio(envioAux.getCodigoBarras(), codigoGestion, responsable, con);
			ConstantesGenerales.getInstance();
			if(!listOrdenes_.contains(envioAux.getNumeroOrden()) && codigoGestion.equals(ConstantesGenerales.GESTION_ALISTAMIENTO)){
			    listOrdenes_.add(envioAux.getNumeroOrden());
			}
                    }
                    else{
                        errores.put(codigoActual, CoreServicesSource.getInstance().getCoreServicesSetupKey("inconsistenciaEnvioGestionInvalida"));
                    }
                }
            }
	     errores.put("ORDENES", listOrdenes_);
        }
        catch (Exception e) {
            throw new DAOException("EnvioDAO:updateGestionEnvios: " + e.toString(), e);
        }
        finally {
            closeConnection(con, null);
        }
        return errores;
    }
    
   /**
    * Actualiza el campo CODIGO_ULTIMA_GESTION de la tabla ENVIO con el valor
    * recibido en el parametro codigoGestion, para los envios en el rango de
    * envios recibido como parametro
    *
    * @param codigoInicio String con el codigo de barras inicial del rango.
    * @param codigoFinal String con el codigo de barras final del rango.
    * @param codigoGestion String con el nuevo codigo de gestion
    * @param responsable nombre de usuario en LDAP de la persona que realiza la actualizacion
    * @return Hashtable con los envios que no se pudieron actualizar, este Hashtable tiene
    *         como key el codigo de barras y como valor el codigo de error segun los codigos
    *         de error del bundle DespachosSetup.properties.
    */
    public Hashtable updateGestionEnvios(String codigoInicio,String codigoFinal,String codigoGestion,String responsable) throws DAOException{
        Hashtable errores = new Hashtable();
        Connection con = null;
        PreparedStatement statement = null;
        ResultSet rs = null;
	ArrayList listOrdenes_=new ArrayList();
        try {
            con = getConnectionDB2();
            statement = con.prepareStatement("SELECT CODIGO_BARRAS, CODIGO_ULTIMA_GESTION , NUMERO_ORDEN " +
                                             "FROM " + ConstantesGenerales.getInstance().SCHEMA + ".ENVIO " +
                                             "WHERE CODIGO_BARRAS BETWEEN ? AND ?");
            statement.setString(1, codigoInicio);
            statement.setString(2, codigoFinal);
            rs = statement.executeQuery();
            int actualizados = 0;
            while (rs.next()) {
                int indice = 0;
                EnvioDto envioAux = new EnvioDto();
                envioAux.setCodigoBarras(rs.getString(++indice));
                envioAux.setCodigoUltimaGestion(rs.getString(++indice));
		String numOrden=rs.getString(++indice);
		    
                if(validarCambioGestion(codigoGestion,envioAux.getCodigoUltimaGestion())){
                    this.updateGestionEnvio(envioAux.getCodigoBarras(), codigoGestion, responsable,con);
		    ConstantesGenerales.getInstance();
		    if(!listOrdenes_.contains(numOrden) && codigoGestion.equals(ConstantesGenerales.GESTION_ALISTAMIENTO)){
			listOrdenes_.add(numOrden);
		    }
                    actualizados++;
                }else{
                    errores.put(envioAux.getCodigoBarras(), CoreServicesSource.getInstance().getCoreServicesSetupKey("inconsistenciaEnvioGestionInvalida"));
                }
            }
            errores.put("ACTUALIZADOS", Integer.valueOf(actualizados));
	    errores.put("ORDENES", listOrdenes_);
        }
        catch (SQLException e) {
            throw new DAOException("EnvioDAO:updateGestionEnvios: " + e.toString(), e);
        }
        finally {
            closeConnection(con, statement, rs);
        }

        return errores;
    }
    
   /**
    * Valida que el cambio de gestion sea uno de los movimientos validos,
    * retorna true si es valido, false en caso contrario
    *
    * @param codigoGestionNueva String codigo de la nueva gestion del envio
    * @param codigoGestionActual String codigo de la gestion actual del envio
    * @return boolean true si el cambio es valido, false en caso contrario
    */
    private boolean validarCambioGestion(String codigoGestionNueva,String codigoGestionActual){	
        String[] cambios = CoreServicesSource.getInstance().getCoreServicesSetupKey("cambiosGestionValidos").split(";");
        for(int i=0;i<cambios.length;i++){
            String [] parejas = cambios[i].split(",");	
            for(int j=0;j<parejas.length;j++){	
                if(codigoGestionActual.equals(parejas[0]) && codigoGestionNueva.equals(parejas[1]))
                    return true;
            }
        }
        return false;
    }
    
   /**
    * Actualiza el campo CODIGO_ULTIMA_GESTION de la tabla ENVIO con el valor
    * recibido en el parametro codigoGestion, para el envio con codigo de barras igual al
    * codigo de barras recibido como parametro, adicionalmente inserta un registro en la tabla
    * ENVIO_MOVIMIENTO. Operacion atomica
    *
    * @param codigoBarras String con el codigo de barras del envio a actualizar
    * @param codigoGestion String con el nuevo codigo de gestion
    * @param responsable nombre de usuario en LDAP de la persona que realiza la actualizacion
    * @return boolean, true si la actualizacion fue correcta, false en caso contrario
    */
    private boolean updateGestionEnvio(String codigoBarras,String codigoGestion,String responsable,Connection con) throws DAOException{
        EnvioDto envioDTO = null;
        PreparedStatement statement = null;
        PreparedStatement statementInsert = null;
        boolean autoCommit;
        try {
            autoCommit = con.getAutoCommit();
            con.setAutoCommit(false);
            statement = con.prepareStatement("UPDATE " + ConstantesGenerales.getInstance().SCHEMA + ".ENVIO " +
                                             "SET CODIGO_ULTIMA_GESTION = ?" + 
                                             " WHERE CODIGO_BARRAS = ?");
            statementInsert = con.prepareStatement("INSERT INTO " +
                                                ConstantesGenerales.getInstance().SCHEMA + ".ENVIO_MOVIMIENTO " +
                                                "(CODIGO_BARRAS,CODIGO_GESTION,FECHA_MOVIMIENTO,CODIGO_RESPONSABLE) " +
                                                "VALUES (?,?,?,?)");
            statement.setString(1, codigoGestion);
            statement.setString(2, codigoBarras);
            statement.executeUpdate();

            statementInsert.setObject(1,codigoBarras);
            statementInsert.setObject(2,codigoGestion);
            statementInsert.setTimestamp(3,new Timestamp(new Date().getTime()));
            statementInsert.setObject(4,responsable);
            statementInsert.executeUpdate();
            con.commit();
            con.setAutoCommit(autoCommit);
        }
        catch (SQLException e) {
            try{
                con.rollback();
            }catch(Exception eRoll){
            }
            throw new DAOException("EnvioDAO:updateGestionEnvio: " + e.toString(), e);
        }
        finally {
            closeConnection(null, statement);
            closeConnection(null, statementInsert);
        }
        return true;
    }
    
    public boolean isEnvioExist(String codigoBarras) throws DAOException {
        Connection con = null;
        PreparedStatement statement = null;
        ResultSet rs = null;
        try {
            con = getConnectionDB2();
            statement = con.prepareStatement("SELECT CODIGO_BARRAS " +
                                             "FROM " + ConstantesGenerales.getInstance().SCHEMA + ".ENVIO " +
                                             "WHERE CODIGO_BARRAS = ?");
            int indice = 0;
            statement.setObject(++indice, codigoBarras);
            rs = statement.executeQuery();
            if (rs.next()) {
                return true;
            }
        } 
        catch (SQLException e) {
            throw new DAOException("ClienteDAO:getClientes: " + e.toString(), e);
        }
        finally {
            closeConnection(con, statement, rs);
        }
        return false;
    }
}